/*
 * Copyright 2010 - 2011, The PLDesktop Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef PL_C_STRING_H
#define PL_C_STRING_H

#include <stddef.h>
#if defined __cplusplus
using namespace std;
#endif

#ifdef EXPORT_LOCAL
#undef EXPORT_LOCAL
#endif
#if defined __cplusplus
#define EXPORT_LOCAL extern "C"
#else
#define EXPORT_LOCAL
#endif

#ifndef NULL
#define NULL 0
#endif

/**
 * Get the length of the c string. The string must \0 terminated.
 *
 * @param src The c string to get the length from.
 * @return The length of the string.
 */
EXPORT_LOCAL size_t strlen(const char *src);

/**
 * Get the length of the string. It returns the last \0 in the allocated
 * string with the length of count.
 *
 * @param s The string to get the length for.
 * @param count The count of the allocated c string.
 * @return The length of the string.
 */
EXPORT_LOCAL size_t strnlen(const char *s, size_t count);

/**
 * Copy the string from src to dest.
 *
 * @param dest The destination string.
 * @param src The source string.
 * @return The destination string.
 */
EXPORT_LOCAL char *strcpy(char *dest, const char *src);

/**
 * Copy the string from src to dest with the maximum size of len.
 *
 * @param dest The destination string.
 * @param src The source string.
 * @param len The maximum length to copy.
 * @return The destination string.
 */
EXPORT_LOCAL char *strncpy(char *dest, const char *src, int len);

/**
 * Compare two strings and return a integral indecating the relationship between
 * the two string.
 *
 * @param p1 The first string.
 * @param p2 The string to compare with the second string.
 * @return a integral indecating the relationship between the two string.
 */
EXPORT_LOCAL int strcmp(const char *p1, const char *p2);

/**
 * Compare two strings and return a integral indecating the relationship between
 * the two string.
 *
 * @param p1 The first string.
 * @param p2 The string to compare with the second string.
 * @param n The max number of character to compare.
 * @return a integral indecating the relationship between the two string.
 */
EXPORT_LOCAL int strncmp(const char *p1, const char *p2, int n);

/**
 * Appends the source string to the destination string.
 *
 * @param dest Destination string.
 * @param src Source string.
 * @return The destination string.
 */
EXPORT_LOCAL char *strcat(char *dest, const char *src);

/**
 * Appends the source string to the destination string.
 *
 * @param dest Destination string.
 * @param src Source string.
 * @param n Maximal number of character to append.
 * @return The destination string.
 */
EXPORT_LOCAL char *strncat(char *dest, const char *src, int n);

#if defined __cplusplus
/**
 * Find the first character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the first position that was found.
 */
const char *strchr(const char *str, int target);

/**
 * Find the first character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the first position that was found.
 */
char *strchr(char *str, int target);
#else
/**
 * Find the first character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the first position that was found.
 */
EXPORT_LOCAL char *strchr(const char *str, int target);
#endif

#if defined __cplusplus
/**
 * Find the last character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the last position that was found.
 */
const char *strrchr(const char *str, int target);
/**
 * Find the last character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the last position that was found.
 */
char *strrchr(char *str, int target);
#else
/**
 * Find the last character target in the string str and return the pointer to
 * that position.
 *
 * @param str The string to search in.
 * @param target The character to search for.
 * @return The pointer to the last position that was found.
 */
EXPORT_LOCAL char *strrchr(const char *str, int target);
#endif

/**
 * Set all values of the memory buf to c interprated as unsigned char for the
 * number of n bytes.
 *
 * @param buf The buffer to fill.
 * @param c The character to set.
 * @param n The number of characters to set.
 * @return The pointer to the memory.
 */
EXPORT_LOCAL void *memset(void *buf, int c, size_t n);

/**
 * Set all values of the memory buf to c interprated as unsigned short for the
 * number of n bytes.
 *
 * @param buf The buffer to fill.
 * @param c The character to set.
 * @param n The number of unsigned short to set.
 * @return The pointer to the memory.
 */
EXPORT_LOCAL void *wmemset(void *buf, int c, size_t n);

/**
 * Set all values of the memory buf to c interprated as unsigned int for the
 * number of n bytes.
 *
 * @param buf The buffer to fill.
 * @param c The character to set.
 * @param n The number of unsigned int to set.
 * @return The pointer to the memory.
 */
EXPORT_LOCAL void *dmemset(void *buf, unsigned int c, size_t n);

/**
 * Copy the memory from s2 to s1 with the number of n bytes.
 *
 * @param s1 The memory to copy to.
 * @param s2 The memory to copy.
 * @param n The number of bytes to copy.
 * @return The pointer to the destination memory.
 */
EXPORT_LOCAL void *memcpy(void *s1, const void *s2, size_t n);

/**
 * Move the memory from s2 to s1 with the number of n bytes.
 *
 * @param s1 The memory to move to.
 * @param s2 The memory to move.
 * @param n The number of bytes to move.
 * @return The pointer to the destination memory.
 */
EXPORT_LOCAL void *memmove(void *s1, const void *s2, size_t n);

/**
 * Compare the memorys from p1 and p2 with the length of len. Return a integral
 * and 0 if they have the same data.
 *
 * @param p1 The first memory pointer to compare.
 * @param p2 The second memory pointer to compare too.
 * @param len The length of the memory to compare.
 * @return The integral of the compare 0 if the memory have the same data.
 */
EXPORT_LOCAL int memcmp(const void *p1, const void *p2, size_t len);

#if defined __cplusplus
/**
 * Searches within the first num bytes of the block of memory pointed by
 * ptr for the first occurrence of value (interpreted as an unsigned char),
 * and returns a pointer to it.
 *
 * @param ptr Pointer to the block of memory where the search is performed.
 * @param value Value to be located. The value is passed as an int, but the
 * function performs a byte per byte search using the unsigned char conversion of this value.
 * @param num Number of bytes to be analyzed.
 * @return A pointer to the first occurrence of value in the block of memory pointed by ptr.
 * If the value is not found, the function returns NULL.
 */
const void * memchr ( const void * ptr, int value, size_t num );

/**
 * Searches within the first num bytes of the block of memory pointed by
 * ptr for the first occurrence of value (interpreted as an unsigned char),
 * and returns a pointer to it.
 *
 * @param ptr Pointer to the block of memory where the search is performed.
 * @param value Value to be located. The value is passed as an int, but the
 * function performs a byte per byte search using the unsigned char conversion of this value.
 * @param num Number of bytes to be analyzed.
 * @return A pointer to the first occurrence of value in the block of memory pointed by ptr.
 * If the value is not found, the function returns NULL.
 */
void * memchr ( void * ptr, int value, size_t num );
#else
/**
 * Searches within the first num bytes of the block of memory pointed by
 * ptr for the first occurrence of value (interpreted as an unsigned char),
 * and returns a pointer to it.
 *
 * @param ptr Pointer to the block of memory where the search is performed.
 * @param value Value to be located. The value is passed as an int, but the
 * function performs a byte per byte search using the unsigned char conversion of this value.
 * @param num Number of bytes to be analyzed.
 * @return A pointer to the first occurrence of value in the block of memory pointed by ptr.
 * If the value is not found, the function returns NULL.
 */
EXPORT_LOCAL void * memchr ( const void * ptr, int value, size_t num );
#endif

/**
 * Compares the C string str1 to the C string str2, both interpreted appropiately 
 * according to the LC_COLLATE category of the current locale.
 *
 * @param str1 C string to be compared.
 * @param str2 C string to be compared.
 * @return Returns an integral value indicating the relationship between the strings:
 * A zero value indicates that both strings are equal.
 * A value greater than zero indicates that the first character that does not match has
 * a greater value in str1 than in str2; And a value less than zero indicates the opposite.
 * @todo rewrite
 */
EXPORT_LOCAL int strcoll ( const char * str1, const char * str2 );

/**
 * Scans str1 for the first occurrence of any of the characters that are part of str2,
 * returning the number of characters of str1  read before this first occurrence.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the characters to match.
 * @return The length of the initial part of str1 not containing any of the characters that are part of str2.
 * This is the length of str1 if none of the characters in str2  are found in str1.
 */
EXPORT_LOCAL size_t strcspn ( const char * str1, const char * str2 );

/**
 * Interprets the value of errnum generating a string describing the error that usually
 * generates that error number value in calls to functions of the C library.
 * The returned pointer points to a statically allocated string, which shall not be modified
 * by the program. Further calls to this function will overwrite its content.
 * The error strings produced by strerror depend on the developing platform and compiler.
 * 
 * @param errnum Error number.
 * @return A pointer to the error string describing error errnum.
 */
EXPORT_LOCAL char * strerror ( int errnum );

#if defined __cplusplus
/**
 * Returns a pointer to the first occurrence in str1 of any of the characters that are part
 * of str2, or a null pointer if there are no matches.
 * The search does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the characters to match.
 * @return A pointer to the first occurrence in str1 of any of the characters that are
 * part of str2, or a null pointer if none of the characters of str2 is found in str1 before
 * the terminating null-character.
 * If none of the characters of str2 is present in str1, a null pointer is returned.
 */
const char * strpbrk ( const char * str1, const char * str2 );

/**
 * Returns a pointer to the first occurrence in str1 of any of the characters that are part
 * of str2, or a null pointer if there are no matches.
 * The search does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the characters to match.
 * @return A pointer to the first occurrence in str1 of any of the characters that are
 * part of str2, or a null pointer if none of the characters of str2 is found in str1 before
 * the terminating null-character.
 * If none of the characters of str2 is present in str1, a null pointer is returned.
 */
char * strpbrk ( char * str1, const char * str2 );
#else
/**
 * Returns a pointer to the first occurrence in str1 of any of the characters that are part
 * of str2, or a null pointer if there are no matches.
 * The search does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the characters to match.
 * @return A pointer to the first occurrence in str1 of any of the characters that are
 * part of str2, or a null pointer if none of the characters of str2 is found in str1 before
 * the terminating null-character.
 * If none of the characters of str2 is present in str1, a null pointer is returned.
 */
EXPORT_LOCAL char * strpbrk ( const char * str1, const char * str2 );
#endif

/**
 * Returns the length of the initial portion of str1 which consists only of characters that are part of str2.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the characters to match.
 * @return The length of the initial portion of str1 containing only characters that appear in str2.
 * Therefore, if all of the characters in str1 are in str2, the function returns the length of the entire str1
 * string, and if the first character in str1 is not in str2, the function returns zero.
 */
EXPORT_LOCAL size_t strspn ( const char * str1, const char * str2 );

#if defined __cplusplus
/**
 * Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
 * The matching process does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the sequence of characters to match.
 * @return A pointer to the first occurrence in str1 of any of the entire
 * sequence of characters specified in str2, or a null pointer if the sequence is not present in str1.
 */
const char * strstr ( const char * str1, const char * str2 );

/**
 * Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
 * The matching process does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the sequence of characters to match.
 * @return A pointer to the first occurrence in str1 of any of the entire
 * sequence of characters specified in str2, or a null pointer if the sequence is not present in str1.
 */
char * strstr ( char * str1, const char * str2 );
#else
/**
 * Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
 * The matching process does not include the terminating null-characters.
 *
 * @param str1 C string to be scanned.
 * @param str2 C string containing the sequence of characters to match.
 * @return A pointer to the first occurrence in str1 of any of the entire
 * sequence of characters specified in str2, or a null pointer if the sequence is not present in str1.
 */
EXPORT_LOCAL char * strstr ( const char * str1, const char * str2 );
#endif

/**
 * A sequence of calls to this function split str into tokens, which are sequences of
 * contiguous characters separated by any of the characters that are part of delimiters.
 *
 * @param str C string to truncate. The contents of this string are modified and broken into smaller strings (tokens).
 * Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous
 * successful call to the function ended.
 * @param delimiters C string containing the delimiters.
 * These may vary from one call to another.
 * @return A pointer to the last token found in string.
 * A null pointer is returned if there are no tokens left to retrieve.
 */
EXPORT_LOCAL char * strtok ( char * str, const char * delimiters );

/**
 * Transforms the C string pointed by source according to the current locale and copies the first num characters
 * of the transformed string to destination, returning its length.
 * Alternativelly, the function can be used to only retrieve the length, by specifying a null pointer for
 * destination and zero for num.
 *
 * @param destination Pointer to the destination array where the content is to be copied.
 * It can be a null pointer if the argument for num is zero.
 * @param source C string to be transformed.
 * @param num Maximum number of characters to be copied to destination.
 * @return The length of the transformed string, not including the terminating null-character.
 */
EXPORT_LOCAL size_t strxfrm ( char * destination, const char * source, size_t num );

#endif
